package com.alfy.websocketdemo.demo1;

import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket 客户端
 */
public class WebSocketClientDemo {

    public static void main(String[] args) throws URISyntaxException, InterruptedException {
        WebSocketClientDemo webSocketClientDemo = new WebSocketClientDemo();
        webSocketClientDemo.client1();
        webSocketClientDemo.client2();
    }

    /**
     * 获取 WebSocket 客户端方法
     *
     * @param httpHeaders 其他 HTTP 标头
     * @return {@link WebSocketClient } 返回客户端对象
     * @throws URISyntaxException 异常对象
     */
    private static WebSocketClient getWebSocketClient(Map<String, String> httpHeaders) throws URISyntaxException {
        WebSocketClient webSocketClient = new WebSocketClient(new URI("ws://localhost:8889"), httpHeaders) {

            ServerHandshake handshakedata = null;

            /**
             * open 事件。在执行了打开握手并且给定的 websocket 已准备好写入之后调用（即：成功链接上服务端）。
             *
             * @param serverHandshake   websocket 实例的握手
             */
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
                handshakedata = serverHandshake;
                String clientName = handshakedata.getFieldValue("clientName");
                System.out.println(clientName + "成功连接上服务端 ~~~");
            }

            /**
             * message 事件。从远程主机接收的字符串消息的回调
             *
             * @param message       接收到的 UTF-8 解码消息
             */
            @Override
            public void onMessage(String message) {
                String clientName = handshakedata.getFieldValue("clientName");
                System.out.println(clientName + "接收到服务端消息（字符串）: " + message);
            }

            /**
             * close 事件，在关闭 websocket 连接后调用。
             *
             * @param code          可以在此处查找代码
             * @param reason        附加信息字符串
             * @param remote        返回连接的关闭是否由远程主机启动
             */
            @Override
            public void onClose(int code, String reason, boolean remote) {
                System.out.println("websocket 连接关闭, code: " + code + "-reason:" + reason + "-remote:" + remote);
            }

            /**
             * error 事件。发生错误时调用。
             * 注：如果错误导致 websocket 连接失败，则将额外调用 onClose(int code, String reason, boolean remote)。
             * 调用此方法的主要原因是 IO 或协议错误。如果给定的异常是 RuntimeException，则可能意味着您遇到了 bug。
             *
             * @param ex 导致此错误的异常
             */
            @Override
            public void onError(Exception ex) {
                System.out.println("client onError, " + ex.getMessage());
            }

            @Override
            public void onWebsocketPong(WebSocket conn, Framedata f) {
                System.out.println("client onWebsocketPong, " + f.getPayloadData() + ", " + f.getOpcode());
                super.onWebsocketPong(conn, f);
            }

            /**
             * 此默认实现将发送一个 pong 以响应收到的 ping。pong 帧将具有与 ping 帧相同的有效负载。
             *
             * @param conn conn
             * @param f    f
             */
            @Override
            public void onWebsocketPing(WebSocket conn, Framedata f) {
                System.out.println("client onWebsocketPing, " + f.getPayloadData() + ", " + f.getOpcode());
                super.onWebsocketPing(conn, f);
            }
        };
        // 开始连接客户端
        webSocketClient.connect();
        // 连接成功返回客户端对象
        return webSocketClient;
    }

    /**
     * 客户端1
     *
     * @throws URISyntaxException   urisyntax exception
     * @throws InterruptedException interrupted exception
     */
    public void client1() throws URISyntaxException, InterruptedException {
        // 设定 http 标头
        Map<String, String> httpHeaders = new HashMap<String, String>();
        httpHeaders.put("clientName", "client1");
        // 创建连接
        WebSocketClient webSocketClient = getWebSocketClient(httpHeaders);
        Thread.sleep(5000);
        // 发送消息1
        webSocketClient.send("我这边是客户端1（字符串）");
        // 发送消息2
        webSocketClient.send("我这边是客户端数据2（byte[]）".getBytes());
        // 发送消息3
        byte[] data = "我这边是客户端数据3（ByteBuffer）".getBytes(); // binary data
        ByteBuffer buffer = ByteBuffer.wrap(data);
        webSocketClient.send(buffer);
    }

    /**
     * client2
     *
     * @throws URISyntaxException   urisyntax exception
     * @throws InterruptedException interrupted exception
     */
    public void client2() throws URISyntaxException, InterruptedException {
        // 设定 http 标头
        Map<String, String> httpHeaders = new HashMap<String, String>();
        httpHeaders.put("clientName", "client2");
        // 创建连接
        WebSocketClient webSocketClient = getWebSocketClient(httpHeaders);
        Thread.sleep(5000);
        // 发送消息1
        webSocketClient.send("我这边是客户端2（字节）".getBytes());
        // 发送消息2
        ByteBuffer buffer = ByteBuffer.wrap("我这边是客户端数据2（二进制）".getBytes()); // binary data
        webSocketClient.send(buffer);
    }

}

// 成功连接上服务端 ~~~
// 接收到服务端消息（字符串）: client1消息接收成功（字符串）~~~
// 接收到服务端消息（字符串）: client1消息接收成功（二进制）~~~
// 接收到服务端消息（字符串）: client1消息接收成功（二进制）~~~
// 成功连接上服务端 ~~~
// 接收到服务端消息（字符串）: client2消息接收成功（二进制）~~~
// 接收到服务端消息（字符串）: client2消息接收成功（二进制）~~~